/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package MemoriaIntermedia;

/**
 *
 * @author UNSAAC73
 */
import java.util.LinkedList;
import java.util.Iterator;
import java.util.logging.Logger;
import java.util.Queue;

public class GestorMemoriaIntermedia 
{
    static final Logger logger = Logger.getLogger("Gestion de Buffer");
    //represetna a los bloques de la 
    // memoria intermedia o buffer;
    private Pagina[] buffer;
    // nro de paginas en total en el buffer
    private int numeroPagina;
    // posicion el buffer de la ultima pagina colocada
    private int posicionUltimaPagina = -1;
    // cola para el control de sustitucion basada en LRU
    private Queue colaLRU; // cual ha sido recienetemente utilizado
    
    public GestorMemoriaIntermedia(int numeroPaginas)
    {
        this.numeroPagina = numeroPaginas;
        // crear el buffer con pagina vacia
        buffer = new Pagina[numeroPaginas];
        // Crear un a cola FIFO
        colaLRU = new LinkedList<Integer>();
        
    }
    
    public Pagina recuperarPaginaDelBuffer(int numeroPagina)
    {
        // Verificar si la pagina esta en el buffer
        int posicion = posicionDePaginaEnBuffer(numeroPagina);
        if (posicion >= 0) // La pagina esta en el bufer
        {
            //Marcar pagina o bloque recientemente referenciado 
            colaLRU.remove(numeroPagina);
            colaLRU.add(numeroPagina);
            // devolver la pagina de buffer al solicitante
            return buffer[posicion];// devuelve la pagina
        }
        return null;// sino encuentra devuelve nulo
    }
    
    /**/
    public Pagina ponerPaginaEnBuffer(Pagina pagina)
    {
        
        // si la pagina esta en el buffer
        if (estaPaginaEnBuffer(pagina))
        {
            // no descartar ninguna pagina o buffer
            return null;// se bede actulaizar el LRU ? TAREA
        }// si la pagina no esta en el buffer
        else if (!bufferLLeno())
        {
            // asignar la nueva pagina en el buffer o pagina libre        
            posicionUltimaPagina++;
            buffer[posicionUltimaPagina] = pagina;
            // Actulaizar la LRU
            colaLRU.remove(posicionUltimaPagina);
            colaLRU.add(posicionUltimaPagina);
            return null;
        }// sil apgina no esta en el buffer, pero sin espacio
        else
        {
            // recuperar la pagina a descartar
            // Identificar el id de pagina a descartar de la colaLRU
            int numeroPaginaDescartada = (Integer) colaLRU.remove();
            // Conocindo ewl id de pagina, ubicar la posicion
            // de la pagina en el buffer
            int posicion = posicionDePaginaEnBuffer(numeroPaginaDescartada);
            // extraer la pagina a descartar del buffer
            Pagina paginaDescartada = buffer[posicion];
            // actualizar la nueva pagina en la posicion de la pagina descartada
            buffer[posicion] = pagina; 
            // hacer que el Id  dela nuva pagina sea el mas recientemente refrenci
            colaLRU.add(pagina.getNumeroPagina());
            
            return paginaDescartada;
        }
    }
    public int posicionDePaginaEnBuffer(int numeroPagina)
    {
        int posicion = -1;
        for(int i = 0; i<buffer.length; i++)
        {
            if ((buffer[i] != null) && (numeroPagina == buffer[i].getNumeroPagina()))
            {
                posicion = i;
                break;
            }
        }
        return posicion;
    }
               
   private boolean estaPaginaEnBuffer(Pagina pagina)
   {
       return (posicionDePaginaEnBuffer
               (pagina.getNumeroPagina()) != -1);
   }
   
   private boolean bufferLLeno()
   {
       return numeroPagina - 1 == posicionUltimaPagina;
   }
   @Override
   public String toString()
   {
       String resultado = "";
       for(int i = 0; i<buffer.length; i++)
       {
           resultado += "Pagina[" + i + "]:" + buffer[i] + "\n";
                    
       }
       return resultado + "\n" + this.colaLRU;
   }
   
   
   //***************************************************************************
   public static void main(String[] args)
   {
       // Crear un Gestor de memoria
       GestorMemoriaIntermedia gestorBuffer = new GestorMemoriaIntermedia(6);
       // Paginas del disco
       System.out.println("Paginas del disco");
       Pagina[] paginas = new Pagina[10];
       for(int i = 0; i<paginas.length;i++)
       {
           Pagina pagina = new Pagina(i,"p"+i);
           paginas[i] = pagina;
           System.out.println(pagina);
       }
       System.out.println("Contenido del Gestor");
       System.out.println(gestorBuffer);
       
       for(int i = 0; i<paginas.length;i++)
       {
           gestorBuffer.ponerPaginaEnBuffer(paginas[i]);
       }
       System.out.println("Contenido de gestor despues de poner bloque");
       System.out.println(gestorBuffer);
       System.out.println("Poner una pagina al buffer");
       Pagina paginaN = new Pagina(10,"p10");
       Pagina paginaE = gestorBuffer.ponerPaginaEnBuffer(paginaN);
       System.out.println(paginaE);
       System.out.println(gestorBuffer);
       
       System.out.println("Recuperar un apagina del buffer");
       Pagina pagina1 = gestorBuffer.recuperarPaginaDelBuffer(7);
       System.out.println(pagina1);
       System.out.println(gestorBuffer);
       
       System.out.println("Recuperar una posicion del buffer");
       Pagina pagina2 = gestorBuffer.recuperarPaginaDelBuffer(5);
       System.out.println(pagina2);
       System.out.println(gestorBuffer);
       
       
   }
}
